package cn.com.dcsgo.service.impl;

import cn.com.dcsgo.common.PageInfo;
import cn.com.dcsgo.constants.CoreConstant;
import cn.com.dcsgo.domain.dto.SysRoleQueryDTO;
import cn.com.dcsgo.domain.dto.SysRoleSaveDTO;
import cn.com.dcsgo.domain.dto.SysRoleUpdateDTO;
import cn.com.dcsgo.domain.po.SysRole;
import cn.com.dcsgo.domain.po.SysUser;
import cn.com.dcsgo.mapper.SysRoleMapper;
import cn.com.dcsgo.service.SysRoleService;
import cn.com.dcsgo.utils.ConverterUtils;
import cn.com.dcsgo.utils.ServletUtils;
import cn.hutool.core.lang.Assert;
import com.github.pagehelper.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SysRoleServiceImpl
 * TODO admin用户修改角色权限后使关联用户登陆失效
 *
 * @author Dcsgo
 * @since 1/6/2025 下午 2:21
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl implements SysRoleService {
    private final SysRoleMapper sysRoleMapper;

    @Override
    public PageInfo<SysRole, SysRoleQueryDTO> page(PageInfo<SysRole, SysRoleQueryDTO> pageInfo) {
        Page<SysRole> sysRolePage = this.startPage(pageInfo.getPageNumber(), pageInfo.getPageSize());
        List<SysRole> sysRoleList;
        // 管理员 直接返回所有角色信息
        if (getCurrentUser().getUserType().equals(CoreConstant.USER_TYPE_ADMIN)) {
            sysRoleList = sysRoleMapper.selectByRoleNameAndStatus(pageInfo.getParams());
        } else {
            // 其他用户 通过多表查询获取其拥有的角色信息
            sysRoleList = sysRoleMapper.selectByRoleNameAndStatusAndUserId(pageInfo.getParams(), getCurrentUser().getUserId());
        }

        pageInfo.setList(sysRoleList);
        pageInfo.setTotalCount(sysRolePage.getTotal());
        pageInfo.setTotalPage(sysRolePage.getPages());
        return pageInfo;
    }

    @Override
    public SysRole get(Long roleId) {
        return sysRoleMapper.selectByPrimaryKey(roleId);
    }

    @Transactional(rollbackFor = {Throwable.class})
    @Override
    public int save(SysRoleSaveDTO saveDTO) {
        SysRole saveData = new SysRole();
        BeanUtils.copyProperties(saveDTO, saveData);

        saveData.setCreateBy(getUsername());
        saveData.setCreateTime(new Date());
        return sysRoleMapper.insertSelective(saveData);
    }

    @Transactional(rollbackFor = {Throwable.class})
    @Override
    public int update(SysRoleUpdateDTO updateDTO) {
        SysRole updateData = sysRoleMapper.selectByPrimaryKey(updateDTO.getRoleId());
        Assert.notNull(updateData, "更新的角色信息（其角色编号为" + updateDTO.getRoleId() + "）不存在");
        ConverterUtils.syncFieldsWithNullOnEqual(updateDTO, updateData, "roleId");

        updateData.setUpdateBy(getUsername());
        updateData.setUpdateTime(new Date());

        updateData.setCreateTime(null);
        updateData.setCreateBy(null);

        // 角色状态更新 使缓存的权限失效
        if (updateData.getStatus() != null
                && !getCurrentUser().getUserType().equals(CoreConstant.USER_TYPE_ADMIN)) {
            ServletUtils.getSession().invalidate();
        }

        return sysRoleMapper.updateByPrimaryKeySelective(updateData);
    }

    @Transactional(rollbackFor = {Throwable.class})
    @Override
    public int remove(Long roleId) {
        int row = sysRoleMapper.deleteByPrimaryKey(roleId);

        // 删除用户角色表中的关联数据
        row += sysRoleMapper.deleteUserRoleByRoleId(roleId);
        // 删除角色菜单表中的关联数据
        row += sysRoleMapper.deleteRoleMenuByRoleId(roleId);

        // 角色数据更新 使缓存的权限失效
        if (!getCurrentUser().getUserType().equals(CoreConstant.USER_TYPE_ADMIN)) {
            ServletUtils.getSession().invalidate();
        }

        return row;
    }

    @Override
    public List<Long> getLeafMenuIds(Long roleId) {
        return sysRoleMapper.selectLeafMenuIdListByRoleId(roleId);
    }

    @Transactional(rollbackFor = {Throwable.class})
    @Override
    public int save(Long roleId, List<Long> menuIds) {
        // 删除角色原有的权限
        int row = sysRoleMapper.deleteRoleMenuByRoleId(roleId);
        // 添加新的权限
        row += sysRoleMapper.batchInsertRoleMenu(roleId, menuIds);

        // 角色数据更新 使缓存的权限失效
        if (!getCurrentUser().getUserType().equals(CoreConstant.USER_TYPE_ADMIN)) {
            ServletUtils.getSession().invalidate();
        }

        return row;
    }

    @Override
    public List<SysRole> getAll() {
        List<SysRole> sysRoleList;
        SysUser user = getCurrentUser();
        // 管理员直接返回所有角色信息
        if (user.getUserType().equals(CoreConstant.USER_TYPE_ADMIN)) {
            sysRoleList = sysRoleMapper.selectAll();
        } else {
            // 其他用户通过联表查询获取其所拥有的角色信息
            sysRoleList = sysRoleMapper.selectByUserId(user.getUserId());
        }
        return sysRoleList;
    }

    @Override
    public List<Long> getRoleIds(Long userId) {
        return sysRoleMapper.selectByUserId(userId).stream().map(SysRole::getRoleId).collect(Collectors.toList());
    }

    @Transactional(rollbackFor = {Throwable.class})
    @Override
    public int saveUserRoles(Long userId, List<Long> roleIds) {
        // 先删除用户原有的所有角色
        int row = sysRoleMapper.deleteUserRoleByUserId(userId);
        // 批量添加新的角色
        row += sysRoleMapper.batchInsertUserRole(userId, roleIds);

        // 角色数据更新 使缓存的权限失效
        if (!getCurrentUser().getUserType().equals(CoreConstant.USER_TYPE_ADMIN)) {
            ServletUtils.getSession().invalidate();
        }

        return row;
    }
}
